/**
 * 后端服务管理模块
 */

const { spawn } = require('child_process');
const axios = require('axios');
const logger = require('../utils/logger');
const { isPortInUse, waitForPort } = require('../utils/port');

// 后端进程引用
let backendProcess = null;

/**
 * 启动后端服务
 * @param {Object} config - 后端服务配置
 * @returns {Promise<boolean>} 是否启动成功
 */
exports.startBackend = async (config) => {
  try {
    const { jarPath, port, startCommand, startArgs } = config.backend;
    
    // 检查端口是否被占用
    if (await isPortInUse(port)) {
      logger.warn(`端口 ${port} 已被占用，尝试等待服务就绪...`);
      // 检查是否已经有服务在运行
      const isReady = await checkBackendHealth(config);
      if (isReady) {
        logger.info('后端服务似乎已经在运行');
        return true;
      }
      logger.error(`端口 ${port} 被占用且不是有效的后端服务，请先释放该端口`);
      return false;
    }
    
    // 构建启动参数
    const args = [...startArgs, jarPath, `--server.port=${port}`];
    logger.info(`启动后端服务，命令: ${startCommand} ${args.join(' ')}`);
    
    // 启动后端进程
    backendProcess = spawn(startCommand, args, {
      stdio: ['ignore', 'pipe', 'pipe'],
      shell: process.platform === 'win32' // Windows平台需要shell
    });
    
    // 处理标准输出
    backendProcess.stdout.on('data', (data) => {
      const output = data.toString().trim();
      if (output) {
        logger.debug(`[后端输出] ${output}`);
      }
      // 检查启动成功的标志
      if (output.includes('Started') && output.includes('Application')) {
        logger.info('后端服务启动成功！');
      }
    });
    
    // 处理错误输出
    backendProcess.stderr.on('data', (data) => {
      const output = data.toString().trim();
      if (output) {
        logger.error(`[后端错误] ${output}`);
      }
    });
    
    // 处理进程退出
    backendProcess.on('exit', (code) => {
      logger.info(`后端服务已退出，退出码: ${code}`);
      backendProcess = null;
    });
    
    // 处理进程错误
    backendProcess.on('error', (err) => {
      logger.error(`启动后端服务失败: ${err.message}`);
      backendProcess = null;
    });
    
    // 等待服务就绪
    logger.info(`等待后端服务在端口 ${port} 上就绪...`);
    const isReady = await waitForBackendReady(config);
    
    if (isReady) {
      logger.info(`后端服务已成功启动，运行在 http://localhost:${port}`);
      return true;
    } else {
      logger.error('后端服务启动超时');
      // 尝试停止进程
      await exports.stopBackend();
      return false;
    }
  } catch (error) {
    logger.error(`启动后端服务时发生错误: ${error.message}`);
    await exports.stopBackend();
    return false;
  }
};

/**
 * 停止后端服务
 * @returns {Promise<boolean>} 是否停止成功
 */
exports.stopBackend = async () => {
  try {
    if (!backendProcess) {
      logger.info('后端服务未运行');
      return true;
    }
    
    logger.info('正在停止后端服务...');
    
    // 在不同平台上安全地终止进程
    if (process.platform === 'win32') {
      // Windows平台
      backendProcess.kill('SIGTERM');
    } else {
      // Unix-like平台
      backendProcess.kill('SIGINT');
    }
    
    // 设置超时
    const timeoutPromise = new Promise(resolve => 
      setTimeout(() => resolve(false), 10000)
    );
    
    // 等待进程退出
    const exitPromise = new Promise(resolve => {
      backendProcess.once('exit', () => {
        backendProcess = null;
        resolve(true);
      });
    });
    
    const success = await Promise.race([exitPromise, timeoutPromise]);
    
    if (!success) {
      logger.warn('优雅关闭超时，强制终止后端服务');
      if (backendProcess) {
        backendProcess.kill('SIGKILL');
        backendProcess = null;
      }
    }
    
    logger.info('后端服务已停止');
    return true;
  } catch (error) {
    logger.error(`停止后端服务时发生错误: ${error.message}`);
    backendProcess = null;
    return false;
  }
};

/**
 * 检查后端服务状态
 * @param {Object} config - 后端服务配置
 * @returns {Promise<boolean>} 服务是否正在运行
 */
exports.checkBackendStatus = async (config) => {
  try {
    // 检查进程是否在运行
    if (backendProcess && !backendProcess.killed) {
      // 检查端口是否被占用
      const isPortUsed = await isPortInUse(config.backend.port);
      if (isPortUsed) {
        // 检查健康状态
        return await checkBackendHealth(config);
      }
    }
    return false;
  } catch (error) {
    logger.debug(`检查后端服务状态时发生错误: ${error.message}`);
    return false;
  }
};

/**
 * 检查后端服务健康状态
 * @param {Object} config - 后端服务配置
 * @returns {Promise<boolean>} 服务是否健康
 */
function checkBackendHealth(config) {
  const { port, healthCheckPath } = config.backend;
  const url = `http://localhost:${port}${healthCheckPath}`;
  
  // 尝试不同的健康检查路径
  const healthPaths = [
    healthCheckPath,  // 配置的路径
    '/actuator/health', // 标准Spring Boot Actuator路径
    '/health' // 可能的自定义健康检查路径
  ];
  
  // 尝试所有可能的健康检查路径
  const tryHealthPath = async (paths) => {
    if (paths.length === 0) {
      // 所有路径都失败，尝试简单的根路径请求
      return tryRootPath(port);
    }
    
    const currentPath = paths[0];
    const currentUrl = `http://localhost:${port}${currentPath}`;
    
    try {
      const response = await axios.get(currentUrl, {
        timeout: 3000,
        headers: {
          'Accept': 'application/json'
        }
      });
      
      // 检查响应是否表明服务健康
      if (response.status === 200) {
        // 检查多种可能的健康状态格式
        const isHealthy = 
          response.data.status === 'UP' ||
          response.data.health === 'UP' ||
          response.data.status?.toLowerCase() === 'up' ||
          response.data.health?.toLowerCase() === 'up' ||
          // 对于可能没有明确状态字段的响应，只要返回200就认为可用
          Object.keys(response.data).length > 0;
        
        if (isHealthy) {
          logger.debug(`健康检查成功: ${currentUrl}`);
          return true;
        }
      }
    } catch (error) {
      logger.debug(`健康检查失败 [${currentUrl}]: ${error.message}`);
    }
    
    // 当前路径失败，尝试下一个
    return tryHealthPath(paths.slice(1));
  };
  
  // 尝试根路径
  const tryRootPath = async (port) => {
    try {
      const response = await axios.get(`http://localhost:${port}/`, {
        timeout: 3000,
        maxRedirects: 0,
        validateStatus: status => status >= 200 && status < 400
      });
      
      if (response.status >= 200 && response.status < 400) {
        logger.debug(`根路径检查成功，端口 ${port} 上有服务运行`);
        return true;
      }
    } catch (error) {
      // 如果是重定向错误，也认为服务在运行
      if (error.response && (error.response.status === 301 || error.response.status === 302)) {
        logger.debug(`根路径重定向，端口 ${port} 上有服务运行`);
        return true;
      }
      logger.debug(`根路径检查失败: ${error.message}`);
    }
    return false;
  };
  
  return tryHealthPath(healthPaths);
}

/**
 * 等待后端服务就绪
 * @param {Object} config - 后端服务配置
 * @returns {Promise<boolean>} 服务是否在超时前就绪
 */
function waitForBackendReady(config) {
  const { healthCheckTimeout } = config.backend;
  const startTime = Date.now();
  const checkInterval = 1000;
  
  return new Promise((resolve) => {
    const checkHealth = async () => {
      // 检查是否超时
      if (Date.now() - startTime > healthCheckTimeout) {
        resolve(false);
        return;
      }
      
      // 先检查端口是否被占用
      const portInUse = await isPortInUse(config.backend.port);
      if (portInUse) {
        // 然后检查健康状态
        const isHealthy = await checkBackendHealth(config);
        if (isHealthy) {
          resolve(true);
          return;
        }
      }
      
      // 继续检查
      setTimeout(checkHealth, checkInterval);
    };
    
    // 开始检查
    setTimeout(checkHealth, 2000); // 初始延迟
  });
}